package com.haibara.codesubmiteval.aop;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 请求响应日志 AOP
 **/
@Aspect
@Component
@Slf4j
public class LogInterceptor {
    /**
     * 执行拦截
     */
    @Resource
    private ObjectMapper objectMapper;

    @Around("execution(* com.haibara.codesubmiteval.controller.*.*(..)) && !@annotation(com.haibara.codesubmiteval.annotation.NoLog)")
    public Object doInterceptor(ProceedingJoinPoint point) throws Throwable {
        String requestId = UUID.randomUUID().toString().substring(0, 8);
        MDC.put("requestId", requestId);

        HttpServletRequest request = getCurrentRequest();
        Map<String, Object> requestLog = new LinkedHashMap<>();
        requestLog.put("requestId", requestId);
        requestLog.put("path", request.getRequestURI());
        requestLog.put("method", request.getMethod());
        requestLog.put("clientIP", request.getRemoteAddr());
        requestLog.put("userAgent", request.getHeader("User-Agent"));

        Object[] args = point.getArgs();
        String params = args.length > 0 ? JSONUtil.toJsonStr(filterSensitiveParams(args)) : "[]";
        requestLog.put("params", params);

        String requestLogStr = objectMapper
                .enable(SerializationFeature.INDENT_OUTPUT) // 启用美化
                .writeValueAsString(requestLog);
        log.info("\n=== 请求记录 ===\n{}", requestLogStr);
        Object result;
        try {
            result = point.proceed();
        } finally {
            MDC.clear();
        }
        return result;
    }

    private HttpServletRequest getCurrentRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
                .getRequest();
    }

    // 过滤敏感参数
    private Object[] filterSensitiveParams(Object[] args) {
        return args;
    }
}

